<?php
declare(strict_types=1);

namespace Service\OrderService\Volidate;

use Service\BaseService;
use App\Model\BbcModel\Address;
use Service\AreaService\AreaService;
use Service\Code\Normal;
use Service\PayService\CashPayService;
use Service\StoreCardService\StoreCardService;
use App\Model\BbcModel\Member;
use Service\UserService\MnUserService;
use Service\MemberService\MemberService;
use Service\ConfigureService\ChannelConfigService;
use Service\GoodsService\ChannelGoodsService;
use Service\GoodsService\MnGoodsService;
use Service\GoodsService\GoodsBatchService;
use Service\ChannelService\StoreConfigService;
use App\Model\BbcModel\GoodsSale;
use Service\GoodsService\GoodsSaleService;

/**
 * 收银机参数校验
 * @author chenshubo
 */
class CashOrderVolidate extends BaseService
{
    const BONDED_ORDER_TYPE = 4;
    
    protected $_check_field = 
    [
        'price_total'   => '商品总价不能为空',
        'price_order'   => '订单总价不能为空',
        'goods_num'     => '商品总数量不能为空',
        'goods'         => '下单商品明细不能为空',
        'pay'           => '支付信息不能为空'
    ];
    
    /**
     * 校验下单参数
     * @param int $cid
     * @param int $mn_sid
     * @param array $param
     * @return mixed
     */
    public function checkOrderData(int $cid ,int $mn_sid, array $param = [])
    {
        
        foreach ($this->_check_field as $key => $message) 
        {
            if( empty($param[$key]) ) 
            {
                return Normal::returnCode(Normal::FAIL,$message);
            }
        }
        
        //检查地址
        if( isset($param['address_id']) && !empty($param['address_id']) ) {
            $result = $this->getOrderAddress((int)$param['address_id']);
            if( $result['code'] != Normal::SUC ) {
                return $result;
            }
            $param['address']=$result['data'];
        }
        
        
        //检查支付参数
        $pay = @json_decode($param['pay'],true);
        if( empty($pay) ) {
            return Normal::returnCode(Normal::FAIL, '支付方式不能为空');
        }
        
        //$payerCheck = $this->getOrderPayChannel($pay,$param);
        $pay_method =$param['order_type']==self::BONDED_ORDER_TYPE?CashPayService::PRODUCT_BONDED_ORDER_PAY: CashPayService::PRODUCT_NORMAL_ORDER_PAY;
        $payerCheck = CashPayService::instance()->getPayChannel($pay, $param, $pay_method);
        if( $payerCheck['code'] != Normal::SUC ) {
            return $payerCheck;
        }
        
        $param          = $payerCheck['data'];
        $mn_user        = MnUserService::getMnUserInfoByMnSid($mn_sid);
        $mn_user_level  = $mn_user['level'];
        $order_type     = $param['order_type'];
        $mid            = $param['mid'] ?? 0 ;
        $buyer          = [];
        
        //保税自提类型
        if( $order_type == self::BONDED_ORDER_TYPE ) 
        {
            $result_check_bonded = $this->checkBondedGoodsOrderInfo($mn_user,$param);
            if( $result_check_bonded['code'] != Normal::SUC ) {
                return $result_check_bonded;
            }
            $param = $result_check_bonded['data'];
            $buyer = $param['address']['buyer']; 
        }
        
        $param['buyer']     = $buyer;
        $param['mn_user']   = $mn_user;

        //检查下单商品情况
        return $this->checkOrderGoods($cid,$mn_sid,$mn_user_level,$param);
    }
    
    /**
     * 检查下单商品情况 
     * @param int $cid
     * @param int $mn_sid
     * @param int $mn_user_level
     * @param array $param
     * @return mixed
     */
    public function checkOrderGoods(int $cid,int $mn_sid,int $mn_user_level,array $param = [])
    {
        $goods= @json_decode($param['goods'],true);
        if( empty($goods) ) {
            return Normal::returnCode(Normal::FAIL, '商品列表不能为空');
        }
        
        //初始化价格
        $price_total    = 0;
        $total_cost     = 0;
        $pay_total      = 0;
        $total_channel_cost = 0;
        
        $goodsIds = array_column($goods,'goods_id');
        if( empty($goodsIds) ) {
            return Normal::returnCode(Normal::FAIL, '下单商品信息goods_id参数不存在,请联系管理员核对!');
        }
        
        $batchIds = array_column($goods,'batch_id');
        if( empty($batchIds) ) {
            return Normal::returnCode(Normal::FAIL, '下单商品信息batch_id参数不存在,请联系管理员核对!');
        }

        //获取价格设置配置
        $settingPriceConfig = ChannelConfigService::instance()->getChannelConfig('price_decimal',$cid);
        $settingPrice = $settingPriceConfig['price'] ?? 0 ;
        
        //原始商品数据获取
        $goodsList = ChannelGoodsService::instance()->queryGoodsList($goodsIds);
        $goodsListMap = array_column($goodsList,null,'id');
        
        //店铺商品数据获取
        $mn_sid = $param['mn_sid'];
        $mnGoodsList = MnGoodsService::instance()->queryMnGoodsList($mn_sid,$goodsIds);
        $mnGoodsListMap = array_column($mnGoodsList,null,'goods_id');
        
        //店铺商品批次信息获取
        $mnGoodsBatchList = GoodsBatchService::instance()->getGoodsBatchListByIDs($mn_sid, $goodsIds,$batchIds);
        $mnGoodsBatchListMap = GoodsBatchService::instance()->getMapGoodsBatchList($mnGoodsBatchList);
        
        //计算商品收益率
        $profitGoodsPriceLists = MnGoodsService::instance()->getGoodsAllProfit($mn_sid,$goodsIds,1,$mn_user_level);
        $profitGoodsPriceListMap = array_column($profitGoodsPriceLists,null,'goods_id');
        
        //商品销量
        $goodsSaleList = GoodsSaleService::instance()->queryGoodsList($cid,$goodsIds);
        $goodsSaleListMap = array_column($goodsSaleList,null,'goods_id');
        
        //订单类型
        $order_type = $param['order_type'];
        
        $total_price_tax=0;
        
        foreach ($goods as $key => & $value)
        {
            if( empty($value['goods_id']) ) {
                return Normal::returnCode(Normal::FAIL,"下单参数goods.goods_id缺失");
            }
            
            if( empty($value['num']) ) {
                return Normal::returnCode(Normal::FAIL,"下单参数goods.num缺失");
            }
            
            if( empty($value['batch_id']) ) {
                return Normal::returnCode(Normal::FAIL,'下单参数goods.batch_id批次信息必传');
            }
            
            $goods_id   = $value['goods_id'];
            $batch_id   = $value['batch_id'];
            $goods_num  = (int)$value['num'];
            if(empty($goodsListMap[$goods_id])) {
                return Normal::returnCode(Normal::FAIL,"商品ID数据[{$goods_id}]不存在，请选择其它商品进行下单!");
            }
            
            $goodsinfo  = $goodsListMap[$goods_id];
            $goods_name = $goodsinfo['name'];
            $is_bonded  = $goodsinfo['is_bonded'];
            
            //保税商品类型判断
            if( $is_bonded == 1 ) 
            {
                if( isset($param['order_type']) && $param['order_type'] != self::BONDED_ORDER_TYPE ) {
                    return Normal::returnCode(Normal::FAIL,"订单类型错误,非保税订单商品【{$goods_name}】为保税商品");
                }
                
//                if( $goodsinfo['num_storage'] < $goods_num ) {
//                    return Normal::returnCode(Normal::FAIL, "商品【{$goods_name}】保税仓库存不足");
//                }
                
                if( $goodsinfo['tax_rate']>0&&( !isset($value['price_tax']) || $value['price_tax'] <= 0 )) {
                    return Normal::returnCode(Normal::FAIL,"商品【{$goods_name}】保税税金错误");
                }
                
                if( $goodsinfo['df']==1 || $goodsinfo['status']==0 ) {
                    return Normal::returnCode(Normal::FAIL,"保税商品【{$goods_name}】渠道已被下架");
                }
                $currey_price_tax=$value['price_tax']??0;
                $currey_price_tax = $currey_price_tax * $value['num'];
                $total_price_tax= bcadd((string)$total_price_tax, (string)$currey_price_tax,2);
            }
            
            //校验是否属于店铺商品
            if( empty($mnGoodsListMap[$goods_id])) { 
                return Normal::returnCode(Normal::FAIL, "店铺商品【{$goods_name}】不存在");
            }
            
            $mn_store_goods = $mnGoodsListMap[$goods_id];
            if( $mn_store_goods['storestatus'] == 0 ) {
                return Normal::returnCode(Normal::FAIL,"店铺商品【{$goods_name}】已下架");
            }
            
            if( $mn_store_goods['quantity'] < $goods_num ) {
                return Normal::returnCode(Normal::FAIL,"店铺商品【{$goods_name}】库存不足");
            }
            
            if( !(!empty($mnGoodsBatchListMap[$goods_id]) && !empty($mnGoodsBatchListMap[$goods_id][$batch_id])) ) {
                return Normal::returnCode(Normal::FAIL,"店铺商品【{$goods_name}】批次信息[{$goods_id}-{$batch_id}]不存在");
            }
            
            $goodsBatch = $mnGoodsBatchListMap[$goods_id][$batch_id];
            if( $goodsBatch['num'] < $goods_num ) {
                return Normal::returnCode(Normal::FAIL, "店铺商品【{$goods_name}】批次信息[{$goods_id}-{$batch_id}]库存不足");
            }
            
            if( empty($profitGoodsPriceListMap[$goods_id]) ) {
                return Normal::returnCode(Normal::FAIL, "店铺商品【{$goods_name}】不存在，请确认!");
            }
            
            //利润额价格
            $profit = $profitGoodsPriceListMap[$goods_id];            
            $price_store = (string)$profit['price_store'];
            
            //商品成本价
            $value['price_cost'] = $mn_store_goods['average_price'] ? $mn_store_goods['average_price'] : $price_store;
            
            //如果是保税订单类型
            if( $order_type == self::BONDED_ORDER_TYPE ) {
                $value['price_cost'] = $price_store;
            }

            $goods_num                        = (string)$goods_num;
            $value['price']                   = bcadd($price_store, (string)$profit["profit"], 2);
            $value['price_vip']               = bcadd($price_store, (string)$profit['profit_vip'], 2);
            $value['goods_name']              = $goods_name;
            $value['barcode']                 = $goodsinfo['barcode'];
            $value['skucode']                 = $goodsinfo['skucode'];
            $value['img']                     = $goodsinfo['img'];
            $value['is_bonded']               = $is_bonded;
            $value['channel_cost']            = bcmul((string)$goodsinfo['price_cost'], $goods_num, 2);
            $value['is_combine_goods']        = $goodsinfo['is_combine_goods'];
            $value['combine_goods_json_body'] = $goodsinfo['combine_goods_json_body'];
            $value['combine_goods_json_body'] = $goodsinfo['combine_goods_json_body'];
            $value['tax_rate']                = $goodsinfo['tax_rate'];
            $value['high_price']              = $goodsinfo['high_price'];
            $value['supplier_id']             = $goodsinfo['supplier_id'];
            $value['store_isCombineOrders']   = $goodsBatch['store_isCombineOrders'];
            $value['high_tax_rate']           = $goodsinfo['high_tax_rate'];
            $value['is_trade']                = $goodsinfo['is_trade'];
            
            $tax_rate = (string)$goodsinfo['tax_rate'];
            //之前是把税费踢出去
            // if( $order_type == self::BONDED_ORDER_TYPE && $goodsinfo['tax_free'] == 1 && $goodsinfo['is_bonded'] == 1 )
            // {
            //     $new_tax_rate= bcadd('1', $tax_rate,2);
            //     $value['price_cost'] = bcdiv($price_store,(string)$new_tax_rate,2);
            // }

            //现在要求把不含税的税费加回去
            if( $order_type == self::BONDED_ORDER_TYPE && $goodsinfo['tax_free'] == 0 && $goodsinfo['is_bonded'] == 1 )
            {
                $new_tax_rate= bcadd('1', $tax_rate,2);
                $value['price_cost'] = bcmul($price_store,(string)$new_tax_rate,2);
            }
            
            //保税商品
            if( $is_bonded == 1 )
            {
                $value['supplier_name'] = $goodsinfo['supplier_name'];
                $value['spec_num']      = $goodsinfo['base_spec'];
                $value['unit']          = $goodsinfo['base_spec'].$goodsinfo['unit_name'];
                
                if( $goodsinfo['tax_free'] == 0 ) {
                    $value['price']= bcadd((string)$value['price'], bcmul((string)$value['price'], (string)$goodsinfo['tax_rate'],2),2);
                    $value['price_vip']= bcadd((string)$value['price_vip'], bcmul((string)$value['price_vip'], (string)$goodsinfo['tax_rate'],2),2);
                }
                //保税自提暂时不根据配置收取尾数
//                if( $settingPrice == 0 ) { 
//                    $value['price']     = upDecimal((string)$value['price'],1);
//                    $value['price_vip'] = upDecimal((string)$value['price_vip'],1);
//                } else {
//                    $value['price']     = ceil((string)$value['price']);
//                    $value['price_vip'] = ceil((string)$value['price_vip']);
//                }
            }

            
            //$price_total= bcadd($price_total, bcmul($value['price_actual'],$goods_num,2),2);
            $price_total        = bcadd((string)$price_total,(string)$value['price_total'],2);
            $total_cost         = bcadd((string)$total_cost,bcmul((string)$value['price_cost'],(string)$goods_num,2),2);
            $pay_total          = bcadd((string)$pay_total,(string)$value['price_pay'],2);
            $total_channel_cost = bcadd((string)$total_channel_cost,(string)$value['channel_cost'],2);
        }
        
        if( bccomp((string)$price_total,(string)$param['price_total'],2) != 0 ) {
            return Normal::returnCode(Normal::FAIL,"下单商品总价【{$param['price_total']}】 和 实际计算商品总价【{$price_total}】不能相等，请确认商品金额是否正确！");
        }
        
        if($param['order_type']==self::BONDED_ORDER_TYPE){
            if( $param['tax_fee'] != $total_price_tax ){
                return Normal::returnCode(Normal::FAIL, '保税自提订单,订单税费有误');
            }
        }
        
        $param['goods']                 = $goods;
        $param['total_cost']            = $total_cost;
        $param['pay_total']             = $pay_total;
        $param['total_channel_cost']    = $total_channel_cost;
        $param['mnGoodsListMap']        = $mnGoodsListMap;
        $param['mnGoodsBatchListMap']   = $mnGoodsBatchListMap;
        $param['goodsListMap']          = $goodsListMap;
        $param['goodsSaleListMap']      = $goodsSaleListMap;
        return Normal::returnCode(Normal::SUC,'下单价格计算完成',$param);
    }
    
    /**
     * 检查保税订单参数
     * @param array $mn_user
     * @param array $param
     */
    public function checkBondedGoodsOrderInfo(array $mn_user, array $param = [] )
    {
        $order_money_limit='';
        $cashregister_limit_config=StoreConfigService::instance()->getConfig('cashregister_limit',$mn_user['id']);
        if(isset($cashregister_limit_config['order_money_limit'])){
            $order_money_limit=$cashregister_limit_config['order_money_limit'];
        }
        if(!empty($order_money_limit)&&$param['price_order']>$order_money_limit){
            return Normal::returnCode(Normal::FAIL, "据海关政策要求，单笔保税订单金额不能超过{$order_money_limit}元，请再次确定订单金额");
        }
//        if( count($param['pay_way']) > 1 ) {
//            return Normal::returnCode(Normal::FAIL, '保税订单不允许混合支付');
//        }
        
        if( empty($param['mid']) ) {
            return Normal::returnCode(Normal::FAIL, '保税订单必须录入会员');
        }
        
        $mid = $param['mid'];
        $memberInfo = MemberService::instance()->getMemberInfoByMid($mid);
        if( empty($memberInfo['truename']) ) {
            return Normal::returnCode(Normal::FAIL, '购买者会员真实姓名不能为空');
        }
        
        if( empty($memberInfo['idcard']) ) {
            return Normal::returnCode(Normal::FAIL, '购买者会员身份证号码不能为空');
        }
        
        if( empty($memberInfo['mobile']) ) {
            return Normal::returnCode(Normal::FAIL, '购买者会员手机号码不能为空');
        }
        
        if( $mn_user['province'] == 0 ) {
            return Normal::returnCode(Normal::FAIL, '保税自提订单,请配置门店自提收货地址[省份]');
        }
        
        if( $mn_user['city'] == 0 ) {
            return Normal::returnCode(Normal::FAIL, '保税自提订单,请配置门店自提收货地址[市]');
        }
        
        if( $mn_user['area'] == 0 ) {
            return Normal::returnCode(Normal::FAIL, '保税自提订单,请配置门店自提收货地址[区/县]');
        }
        
        if( empty($mn_user['address']) ) {
            return Normal::returnCode(Normal::FAIL, '保税自提订单,请配置门店自提收货地址[详细地址]');
        }
        
//        if( empty($param['tax_fee']) || $param['tax_fee'] <= 0 ){
//            return Normal::returnCode(Normal::FAIL, '保税自提订单,订单税费有误');
//        }
        
        if(!isset($param['express_type'])){
            return Normal::returnCode(Normal::FAIL, '保税自提订单,提货类型必传');
        }
        
        if(!isset($param['express'])){
            return Normal::returnCode(Normal::FAIL, '保税自提订单,收货地址必填,json');
        }
        
        $express= @json_decode($param['express'],TRUE);
        $param['express']=$express;
        if(empty($express['express_province'])||empty($express['express_city'])||empty($express['express_area'])||empty($express['express_address'])||empty($express['express_mobile'])||empty($express['express_name'])){
            return Normal::returnCode(Normal::FAIL, '保税自提订单,收货地址必填');
        }
        
        
        $areas = AreaService::instance()->queryAreaListById([
            $express['express_province'],
            $express['express_city'],
            $express['express_area']
        ]);
        
        $param['address'] = [
            'id'            => 0,
            'true_name'     => $express['express_name']??$memberInfo['truename'],
            'idcard'        => $memberInfo['idcard'],
            'mobile'        => $express['express_mobile'],
            'province'      => $areas[$express['express_province']],
            'city'          => $areas[$express['express_city']],
            'area'          => $areas[$express['express_area']],
            'address'       => $express['express_address'],
            'is_default'    => 0,
            'md'            => time(),
            'postage'       => 0,
            'buyer'         => [
                'truename'  => $memberInfo['truename'],
                'idcard'    => $memberInfo['idcard'],
                'mobile'    => $memberInfo['mobile']
            ]
        ];
        return Normal::returnCode(Normal::SUC,'获取成功',$param);
    }
    
    /**
     * 处理下单地址
     * @param int $address_id
     */
    public function getOrderAddress( int $address_id )
    {
        $address = Address::instance()->info(['id'=>$address_id]);
        if( empty($address) ) {
            return Normal::returnCode(Normal::FAIL,'未找到收货地址信息');
        }
        
        $result = $this->queryAdressByIDs($address);
        if( $result['code'] != Normal::SUC ) {
            return $result;
        }
        
        $areas = $result['data'];
        $address = [
            'id'            => $address['id'],
            'true_name'     => $address['true_name'],
            'idcard'        => $address['idcard'],
            'mobile'        => $address['mobile'],
            'province'      => $areas[$address['province']],
            'city'          => $areas[$address['city']],
            'area'          => $areas[$address['area']],
            'address'       => $address['address'],
            'is_default'    => $address['is_default'],
            'md'            => $address['md'],
            'postage'       => 0
        ];
        return Normal::returnCode(Normal::SUC,"地址获取成功",$address);
    }
    
    /**
     * 查询地址信息
     * @param array $areaIds
     */
    public function queryAdressByIDs( array $address = [] )
    {
        $province = $address['province'];
        $city = $address['city'];
        $area = $address['area'];
        $areas = AreaService::instance()->queryAreaListById([
            $province,
            $city,
            $area
        ]);
        if( empty($areas[$province]) ) {
            return Normal::returnCode(Normal::FAIL,"省份地址ID[{$province}]识别异常");
        }
        
        if( empty($areas[$city]) ) {
            return Normal::returnCode(Normal::FAIL,"市/县地址ID[{$city}]识别异常");
        }
        
        if( empty($areas[$area]) ) {
            return Normal::returnCode(Normal::FAIL,"地区地址ID[{$area}]识别异常");
        }
        
        return Normal::returnCode(Normal::SUC,"获取成功",$areas);
    }
    
    /**
     * 根据前端提供支付参数确认支付信息
     * @param array $payInfo
     * @param array $body
     */
    public function getOrderPayChannel( array $pay = [], array $param = [] )
    {
        $pay_way = [];
        $money   = '0.00';
        $order_type = $param['order_type'];
        foreach ($pay as $key => $value)
        {
            if( empty($value['pay_type']) ) {
                return Normal::returnCode(Normal::FAIL,"支付方式参数缺失[pay_type]");
            }
            
            $pay_type = $value['pay_type'];
            if( !isset(CashPayService::$_cash_payer[$pay_type]) ) {
                return Normal::returnCode(Normal::FAIL,"支付方式[{$pay_type}]不存在,请检查！");
            }
            
            $pay_way[] = $pay_type;
            $payer = CashPayService::$_cash_payer[$pay_type];
            if( $order_type == self::BONDED_ORDER_TYPE && $payer['is_support_bonded'] != 1 ) {
                return Normal::returnCode(Normal::FAIL, "保税订单不支持{$payer['pay_name']}");
            }
            
            //当前支付方式支付金额
            $pay_money = (string)$value['pay_money'];
            $param[$payer['pay_code']] = $pay_money;
            $money = bcadd($money,$pay_money, 2);
            
            //需要扫码code
            if( in_array($pay_type,[CashPayService::TYPE_SECE_PAY,CashPayService::TYPE_WEIXIN_SCAN_PAY,CashPayService::TYPE_ALI_SCAN_PAY]) ) {
                $param['scan_code'] = $value['scan_code'];
            }
            
            //储值卡支付
            if( $pay_type == CashPayService::TYPE_STORE_CARD_PAY ) 
            {
                $checkStoreCard = StoreCardService::instance()->checkStoredCard(
                    $param['cid'], 
                    $param['mn_sid'],
                    $value['cstorecard_numid'],
                    $value['storecard_password'],
                    $value['pay_money']
                    );
                if( $checkStoreCard['code'] != Normal::SUC ) {
                    return $checkStoreCard;
                }
                
                $param['storecard_id'] = $checkStoreCard['data']['id'];
            }
            
            //积分支付
            if( $pay_type == CashPayService::TYPE_PIONTS_PAY ) 
            {
                if( !isset($param['mid']) ) {
                    return Normal::returnCode(Normal::FAIL, '使用积分支付的情况下,会员信息mid必传');
                }
                
                $member= Member::instance()->info(['mid'=>$param['mid']]);
                if(empty($member)){
                    return Normal::returnCode(Normal::FAIL, '会员信息错误');
                }
                
                if( $member['points'] < $pay_money ) {
                    return Normal::returnCode(Normal::FAIL, '会员储值积分不足');
                }
            }
        }
        
        $param['pay_way'] = $pay_way;
        if(count(array_intersect($param['pay_way'],[CashPayService::TYPE_SECE_PAY,CashPayService::TYPE_WEIXIN_SCAN_PAY,CashPayService::TYPE_ALI_SCAN_PAY]))>1){
            return Normal::returnCode(Normal::FAIL, '扫码和扫脸不允许多种混合支付');
        }
        
        return Normal::returnCode(Normal::SUC,"获取成功",$param);
    }
}
